package com.billsystem.service;

import ch.qos.logback.core.db.dialect.DBUtil;
import cn.hutool.core.bean.BeanUtil;
import com.billsystem.mapper.AccountMapper;
import com.billsystem.mapper.CategoryMapper;
import com.billsystem.mapper.RecordMapper;
import com.billsystem.mapper.UserMapper;
import com.billsystem.pojo.Account;
import com.billsystem.pojo.Category;
import com.billsystem.pojo.Record;
import com.billsystem.pojo.User;
import com.billsystem.pojo.vo.RecordBc;
import com.billsystem.pojo.vo.RecordVo;
import com.billsystem.util.DateUtil;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.abi.ABICodecException;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.fisco.bcos.sdk.transaction.model.exception.TransactionBaseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;

@Service
public class RecordService {
    ///获取配置文件路劲
    public final String configFile = "src/main/resources/config-example.toml";

    // 初始化BcosSDK对象
    BcosSDK sdk = BcosSDK.build(configFile);
    // 获取Client对象，此处传入的群组ID为1
    Client client = sdk.getClient(Integer.valueOf(1));
    // 构造AssembleTransactionProcessor对象，需要传入client对象，CryptoKeyPair对象和abi、binary文件存放的路径。abi和binary文件需要在上一步复制到定义的文件夹中。
    CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair();
    AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "src/main/resources/abi/", "");


    @Autowired
    private RecordMapper recordMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private UserMapper userMapper;

    public RecordService() throws Exception {
    }

    /*
    增加账单信息
     */
    @Transactional
    public void add(Record record) throws ABICodecException, TransactionBaseException {
        if (record.getIncomeExpend() == '1'){

            recordMapper.addRecord(record);
            RecordBc rbc =BeanUtil.copyProperties(record, RecordBc.class);
            //将rbc传入输入数据库blockchain
            //准备要上传的数据
            String recordId = recordMapper.selectNumber()+1+"";
            String userName = userMapper.queryUserById(rbc.getUid()).getName();
            String spend = rbc.getSpend() + "";
            String comment = rbc.getComment();
            String accountName = accountMapper.queryAccount(rbc.getAid()).getAccountName();
            String incomeExpend="收入";
            //调用智能合约
            //同步方式发送交易

            List<Object> params = new ArrayList<>();
            params.add(recordId);
            params.add(userName);
            params.add(spend);
            params.add(comment);
            params.add(accountName);
            params.add(incomeExpend);
            TransactionResponse transactionResponse = transactionProcessor.sendTransactionAndGetResponseByContractLoader("Record", "0x7c83b15aaff4dee1054fc1560438b1ffbae2fe55", "addRecord", params);

            //给rbc附上区块信息
            rbc.setTransactionHash(transactionResponse.getTransactionReceipt().getTransactionHash());
            rbc.setBlockNumber(Integer.parseInt(transactionResponse.getTransactionReceipt().getBlockNumber().substring(2),16)+"");
            rbc.setBlockHash(transactionResponse.getTransactionReceipt().getBlockHash());

            recordMapper.addRecordtob(rbc);

            //获取到该账单的费用
            double money = record.getSpend();
            //更新账户的信息
            accountMapper.updateAmount(money, record.getUid(), record.getAid());
        }else {
            //获取当前消费的账户id
            int aid=record.getAid();
            double money = accountMapper.queryAccount(aid).getAmount();
            if (record.getSpend()<=money){

                recordMapper.addRecord(record);
                RecordBc rbc =BeanUtil.copyProperties(record, RecordBc.class);
                //将rbc传入输入数据库blockchain
                //准备要上传的数据
                String recordId = recordMapper.selectNumber()+1+"";
                String userName = userMapper.queryUserById(rbc.getUid()).getName();
                String spend = rbc.getSpend() + "";
                String comment = rbc.getComment();
                String accountName = accountMapper.queryAccount(rbc.getAid()).getAccountName();
                String incomeExpend="支出";
                //调用智能合约
                //同步方式发送交易

                List<Object> params = new ArrayList<>();
                params.add(recordId);
                params.add(userName);
                params.add(spend);
                params.add(comment);
                params.add(accountName);
                params.add(incomeExpend);
                TransactionResponse transactionResponse = transactionProcessor.sendTransactionAndGetResponseByContractLoader("Record", "0x7c83b15aaff4dee1054fc1560438b1ffbae2fe55", "addRecord", params);

                //给rbc附上区块信息
                rbc.setTransactionHash(transactionResponse.getTransactionReceipt().getTransactionHash());
                rbc.setBlockNumber(Integer.parseInt(transactionResponse.getTransactionReceipt().getBlockNumber().substring(2),16)+"");
                rbc.setBlockHash(transactionResponse.getTransactionReceipt().getBlockHash());

                recordMapper.addRecordtob(rbc);


                //是支出，金额取反
                double rmoney= record.getSpend();
                rmoney = -rmoney;

                //更新账户的信息
                accountMapper.updateAmount(rmoney, record.getUid(), record.getAid());
            }else {
                throw new IllegalArgumentException("账户余额不足，当前余额：" + money);
            }
        }
    }
    /*
    修改账单信息
     */
    @Transactional
    public void updateRecord(Record record){
        //获取到原来的账单
        Record oldRecord = recordMapper.queryRecord(record.getId());
        //如果新账单的账户类型和老账单不一样
        if (oldRecord.getAid() != record.getAid()) {
            double oldMoney = oldRecord.getSpend();
            double money = record.getSpend();
            if (oldRecord.getIncomeExpend() != '0') {
                oldMoney = -oldMoney;
            }
            if (record.getIncomeExpend() == '0') {
                money = -money;
            }
            //还原
            accountMapper.updateAmount(oldMoney, oldRecord.getUid(), oldRecord.getAid());
            //变更
            accountMapper.updateAmount(money, oldRecord.getUid(), record.getAid());
            //修改账单
            recordMapper.updateRecord(record);
        } else {
            double money = record.getSpend() - oldRecord.getSpend();
            if (record.getIncomeExpend() == '0') {
                money = -money;
            }
            accountMapper.updateAmount(money, oldRecord.getUid(), oldRecord.getAid());
            recordMapper.updateRecord(record);
        }

    }
    /*
    根据id删除账单信息
     */
    @Transactional
    public void deleteRecord(int id){
        //获取到账单
        Record oldRecord = recordMapper.queryRecord(id);
        //获取到该账单的金额
        double money = oldRecord.getSpend();
        if (oldRecord.getIncomeExpend() != '0') {
            money = -money;
        }
        //更新账户的信息
        accountMapper.updateAmount(money, oldRecord.getUid(), oldRecord.getAid());
        //删除该记录
        recordMapper.deleteRecord(id);
    }
    /*
    根据id查询账单
     */
    public Record queryRecord(int id){
        return recordMapper.queryRecord(id);
    }
    /*
    根据用户id以及收入还是支出查看账单
     */
    public List<RecordVo> queryRecordList(int uid, char incomeExpend){
        List<Record> lists= recordMapper.queryRecordList(uid, incomeExpend);
        List<RecordVo> vos = new ArrayList<>(lists.size());
        for(Record record : lists){
            RecordVo vo =BeanUtil.copyProperties(record, RecordVo.class);
            java.util.Date date = vo.getDate();
            vo.setDate(DateUtil.util2sql(date));
            Category category = categoryMapper.queryCategory(record.getCid());
            Account account = accountMapper.queryAccount(record.getAid());
            vo.setCategoryName(category.getName());
            vo.setAccountName(account.getAccountName());
            vos.add(vo);
        }
        return vos;
    }

    /*
    根据用户id查询全部信息
     */
    public List<RecordBc> queryAllRecord(int uid){
        return recordMapper.queryAllRecord(uid);
    }
    /*
    查看今日的账单
     */
    public List<Record> queryRecordToday(Record record){
        return recordMapper.queryRecordToday(record);
    }
    /*
    查询本月账单
     */
    public List<Record> queryRecordThisMonth(Date start, Date end, int uid, char incomeExpend){
        return recordMapper.queryRecordThisMonth(start, end, uid, incomeExpend);
    }
    /*
    查询某种种类消费的总次数。例如买菜5次之类的
     */
    public int queryCountOfCategory(int cid, int uid){
        return recordMapper.queryCountOfCategory(cid, uid);
    }
    /*
    查询某种种类消费的总金额。例如买菜666元之类的
     */
    public double queryCountOfSpend(int cid, int uid){
        return recordMapper.queryCountOfSpend(cid, uid);
    }

}
